//
//  CommunicationManager.m
//  MultiplayerTestGame
//
//  Created by  Stefan Nestorov on 12/25/14.
//  Copyright (c) 2014 Nestorov Engineering. All rights reserved.
//

#import "CommunicationManager.h"
#import <UIKit/UIKit.h>
#import <SFS2XAPIIOS/SmartFox2XClient.h>
#import "GameInfo.h"
#import "LevelAdapter.h"
#import "Globals.h"
#import "InvitationManager.h"
#import "BuddyManager.h"
#import "HeroInfo.h"

@interface CommunicationManager () {
    
    SmartFox2XClient *_smartFoxClient;
    SFSRoom * _gameRoom;
    GameInfo *_gameInfo;
    LevelAdapter *_levelAdapter;
    InvitationManager *_invitationManager;
    BuddyManager *_buddyManager;
    NSString *_currentIpAddress;
    NSTimer* _pingTimer;
}

@end


@implementation CommunicationManager

+ (instancetype)sharedManager
{
    
    static CommunicationManager *sharedMyManager = nil;
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        sharedMyManager = [[self alloc] init];
    });
    
    return sharedMyManager;
    
}

- (instancetype)init
{
    
    if ( self = [super init] ) {
        
        _gameInfo = [GameInfo sharedInfo];
        _levelAdapter = [LevelAdapter sharedAdapter];
        _isConnecting = NO;
        _isLoggedIn = NO;
        
    }
    
    return self;
    
}


- (void)connectToWebService
{
    
    NSString *serverIP = [self getDifferentIpAddress:nil];
    
    [self getWebServiceInfoWithAddress:serverIP];
    
}


- (void)getWebServiceInfoWithAddress:(NSString *)ipAddress
{
    
    _isConnecting = YES;
    
    NSString *serverURL = [NSString stringWithFormat:@"http://%@:8888/Sik3/webService.php", ipAddress];
    
    NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:serverURL]
                                                                   cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                               timeoutInterval:5.0f];
    
    NSString *postParams = [NSString stringWithFormat:@"gameId=1"];
    NSData *postData = [postParams dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:postData];
    
    [NSURLConnection sendAsynchronousRequest:urlRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        
        id parsedData;
        
        if ( data != nil ) {
            parsedData = [NSJSONSerialization JSONObjectWithData:data  options:NSJSONReadingMutableLeaves error:nil];
        }
        
        // There is some Error so try to get Info from different IP Address
        if ( connectionError != nil || data == nil || [parsedData isKindOfClass:[NSDictionary class]] == NO ) {
            
            NSLog(@"### WebService Error: connectionError: %@, response URL: %@, parsedData: %@. Faild connection to IP: %@",connectionError.localizedDescription, response.URL, parsedData, ipAddress);
            
            NSString *otherIpAddress = [self getDifferentIpAddress:_currentIpAddress];
            
            [self getWebServiceInfoWithAddress:otherIpAddress];
            
            return;
            
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [self processParsedData:parsedData];
            [self startSmartFoxClientWithAddress:ipAddress];
        });
        
    }];
    
}


- (void)startSmartFoxClientWithAddress:(NSString *)ipAddress
{
    
    _smartFoxClient = [[SmartFox2XClient alloc] initSmartFoxWithDebugMode:NO delegate:self];
    _smartFoxClient.logger.loggingLevel = LogLevel_ERROR;
    
    ConfigData *config = [[ConfigData alloc] init];
    config.host = ipAddress;
    config.port = 9933;
    config.httpPort = 8080;
    config.zone = @"BasicExamples";
    config.udpHost = ipAddress;
    config.udpPort = 9933;
    config.useBlueBox = YES;
    config.blueBoxPollingRate = 500;
    
    NSLog(@"Init SmartFox with IP: %@", config.host);
    [_smartFoxClient connectWithConfig:config];
    
    _invitationManager = [[InvitationManager alloc] initWithCommunicationManager:self andSFSClient:_smartFoxClient];
    _buddyManager = [[BuddyManager alloc] initWithCommunicationManager:self andSFSClient:_smartFoxClient];
    
}


// Get different IP address than the current IP Address
- (NSString *)getDifferentIpAddress:(NSString *)currentIpAddress
{
    
    NSString *otherIpAddress;
    
    NSString *primaryIp = [[NSUserDefaults standardUserDefaults] objectForKey:PRIMARY_IP_KEY];
    
    // If currentIpAddress is PRIMARY_IP_ADDRESS, try again with SECONDARY_IP_ADDRESS
    if ( [currentIpAddress isEqualToString:PRIMARY_IP_ADDRESS] || [currentIpAddress isEqualToString:primaryIp] ) {
        
        otherIpAddress = SECONDARY_IP_ADDRESS;
        
        NSString *secondaryIp = [[NSUserDefaults standardUserDefaults] objectForKey:SECONDARY_IP_KEY];
        
        // Use IpAddress from NSUserDefaults if there is one
        if ( secondaryIp != nil ) {
            otherIpAddress = secondaryIp;
        }
        
    } else {
        
        // currentIpAddress is Petar's IpAddress or nil, try again with Stefan's IpAddress
        if ( primaryIp != nil ) {
            
            otherIpAddress = primaryIp;
            
        } else {
            
            otherIpAddress = PRIMARY_IP_ADDRESS;
            
        }
        
    }
    
    _currentIpAddress = otherIpAddress;
    
    return otherIpAddress;
    
}


- (BOOL)isConnected
{
    
    return _smartFoxClient.isConnected;
    
}


- (void)processParsedData:(NSDictionary *)parsedData
{
    
    if ( parsedData[PRIMARY_IP_KEY] != nil ) {
        [[NSUserDefaults standardUserDefaults] setObject:parsedData[PRIMARY_IP_KEY] forKey:PRIMARY_IP_KEY];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
    if ( parsedData[SECONDARY_IP_KEY] != nil ) {
        [[NSUserDefaults standardUserDefaults] setObject:parsedData[SECONDARY_IP_KEY] forKey:SECONDARY_IP_KEY];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    
}


#pragma mark - SmartFox Events

- (void)onConnection:(SFSEvent *)evt
{
    
    NSLog(@"onConnection event");
    
    // Get username and password from UserDefaults
    NSString *username = [[NSUserDefaults standardUserDefaults] valueForKey:USERNAME_KEY];
    NSString *password = [[NSUserDefaults standardUserDefaults] valueForKey:PASSWORD_KEY];
    NSInteger gameId = 1;
    
    // Connection succeed
    if ( [evt.params[@"success"] boolValue] == YES ) {
        
        _isConnecting = NO;
        
        // User is Not regstered yet
        if ( password == nil ) {
            
            SFSObject *gameIdObj = [SFSObject new];
            [gameIdObj putInt:GAME_ID_KEY value:gameId];
            
            // Try to register and login with username
            [_smartFoxClient send:[LoginRequest requestWithUserName:username
                                                           password:@""
                                                           zoneName:nil
                                                             params:gameIdObj]];
            
        } else {
            
            // Create NSData object
            NSData *dataFromString = [password dataUsingEncoding:NSUTF8StringEncoding];
            
            // Get NSString from NSData object in Base64
            NSString *base64Encoded = [dataFromString base64EncodedStringWithOptions:0];
            
            SFSObject *passObj = [SFSObject new];
            [passObj putUtfString:CRYPTED_PASSWORD_KEY value:base64Encoded];
            [passObj putInt:GAME_ID_KEY value:gameId];
            
            // Login with real Username and Password
            [_smartFoxClient send:[LoginRequest requestWithUserName:username
                                                           password:password
                                                           zoneName:nil
                                                             params:passObj]];
            
        }
        
    } else {
        
        // Connection failure. Try Again with different IP Address
        NSString *differentIpAddress = [self getDifferentIpAddress:_currentIpAddress];
        [self startSmartFoxClientWithAddress:differentIpAddress];
        
    }
    
}


- (void)onLogin:(SFSEvent *)evt
{
    
    NSLog(@"onLogin event");
    
    SFSObject *data = [evt.params objectForKey:@"data"];
    NSString *password = [data getUtfString:PASSWORD_KEY];

    // If recieved password save it from passed SFSObject
    if ( password != nil ) {
        
        [[NSUserDefaults standardUserDefaults] setObject:password forKey:PASSWORD_KEY];
        [[NSUserDefaults standardUserDefaults] synchronize];
        
        // Post notification to dismiss RegistrationVC
        [[NSNotificationCenter defaultCenter] postNotificationName:DISMISS_REGISTRATION_VC object:nil];
        
    }
    
    _isLoggedIn = YES;
    
    [self startPingTimer];
    [self updateChosenHeroInfo];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:LOGGED_IN object:nil];
    
//    // Must be called to init my BuddyList for future usage
//    [_smartFoxClient send:[InitBuddyListRequest request]];
    
}


- (void)onLoginError:(SFSEvent *)evt
{
    
    // Username is already taken.
    if ( [[evt.params objectForKey:@"errorCode"] integerValue] == 3 ) {
        
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Registration error" message:@"Username is already taken." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];
        
    } else {
        
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Login Error" message:[evt.params objectForKey:@"errorMessage"] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];
        
    }
    
    [self disconnect];
    
}


- (void)onRoomJoin:(SFSEvent *)evt
{
    
    //Check if last joined room is game or lobby room
    SFSRoom* roomJoined = [evt.params objectForKey:@"room"];
    if ( [roomJoined isGame] ) {
        _gameRoom = roomJoined;
        _isInGame = YES;
    } else {
        _gameRoom = nil;
        _isInGame = NO;
    }
    
    NSLog(@"onRoomJoin event : %@", roomJoined.name);
    
}


- (void)disconnect
{
    
    _isConnecting = NO;
    _isLoggedIn = NO;
    [_smartFoxClient disconnect];
    
    [self stopPingTimer];
    
}


- (void)onConnectionLost:(SFSEvent *)evt
{
    
    NSLog(@"onConnectionLost");
    
    [self stopPingTimer];
    
}


- (void)onExtensionResponse:(SFSEvent *)evt
{
    
    SFSObject* params = [evt.params objectForKey:@"params"];
  
    //Check if response comes from the same room as player is now
    NSNumber* sourceRoomID = [evt.params objectForKey:@"sourceRoom"];
    NSInteger myRoomID = _gameRoom.id;
    if ( myRoomID != sourceRoomID.integerValue ) return;
    
    NSLog(@"CMD: %@", [evt.params objectForKey:@"cmd"]);
    
    if ( [[evt.params objectForKey:@"cmd"] isEqualToString:CMD_START_NEW_GAME] ) {
        
        [self handleStartGameResponse:params];
        
//        //For Debug only
//        for (NSString *key in keys) {
//            NSLog(@"%@: %@", key, [evt.params objectForKey:key]);
//        }
    } else if ( [[evt.params objectForKey:@"cmd"] isEqualToString:CMD_MOVE_RESPONSE] && _isInGame ) {
        
        [_levelAdapter handleMoveResponse:params];
        float additionalDelay = [_levelAdapter getAdditionalDelay:params];
        [self.communicationDelegate resetTimerAndShouldShowHint:[[GameInfo sharedInfo] isMyTurn] additionalDelay:additionalDelay];
        
    } else if ( [[evt.params objectForKey:@"cmd"] isEqualToString:CMD_USER_BUSY] ) {
        
        [self handleUserBusyMessage:params];
        
    } else if ( [[evt.params objectForKey:@"cmd"] isEqualToString:CMD_GET_LIST_OF_USERS_FOR_NAME] ) {
        
        [self handleListOfUsersResponse:params];
        
    } else if ( [[evt.params objectForKey:@"cmd"] isEqualToString:CMD_GET_RANKING_LISTS] ) {

        [self handleRankingListResponse:params];
        
    } else if ( [[evt.params objectForKey:@"cmd"] isEqualToString:CMD_CHANGE_CURRENT_PLAYER] && _isInGame) {
        
        [self handleChangeCurrentPlayer:params];
        
    } else if ( [[evt.params objectForKey:@"cmd"] isEqualToString:CMD_FORCED_GAME_OVER] && _isInGame ) {
        
        [self handleForcedGameOver:params];
        
    } else if ( [[evt.params objectForKey:@"cmd"] isEqualToString:CMD_GET_AMOUNT_OF_MONEY] ) {
        
        [self handleGetAmountOfMoney:params];
        
    } else if ( [[evt.params objectForKey:@"cmd"] isEqualToString:CMD_GET_STORE_INFO] ) {
        
        [_levelAdapter handleGetStoreInfo:params];
        
    }

}


-(void)sendJoinToWaitingListRequest
{
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_JOIN_USER_TO_WAITING_LIST params:[SFSObject new] room:nil]];
}


- (void)handleStartGameResponse:(SFSObject*)params
{
    
    [self decreaseEnergy];
    
    _gameInfo.isMyTurn = [params getInt:ID_OF_CURRENT_PLAYER] == _smartFoxClient.mySelf.playerId;
    _gameInfo.localPlayer.playerId = _smartFoxClient.mySelf.playerId;
    
    // Set Player properties from UserVariables
    [self retrieveUsersVariables];
    
    NSLog(@"PlayerId : %zd, PlayerdId that should move: %zd", _smartFoxClient.mySelf.playerId, [params getInt:ID_OF_CURRENT_PLAYER]);
    NSLog(@"Is my turn : %@", _gameInfo.isMyTurn ? @"YES" : @"NO");
    
    [_levelAdapter initGameWithBoard:params];
    
    [self.communicationDelegate resetTimerAndShouldShowHint:[[GameInfo sharedInfo] isMyTurn] additionalDelay:5];
    
}


// Sent in response of my Accept Game Invitation, but the Inviter is now Busy
- (void)handleUserBusyMessage:(SFSObject*)params
{

    NSString *message = [params getUtfString:USER_BUSY_MESSAGE];
    
    // Show the Error on screen
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:message delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
    [alert show];
    
}


// Sent in response of my CMD_GET_LIST_OF_USERS_FOR_NAME request
- (void)handleListOfUsersResponse:(SFSObject*)params
{
    
    SFSArray *sfsListOfUsers = [params getSFSArray:LIST_OF_USER_NAMES];
    NSMutableArray *listOfUsers = [NSMutableArray new];
    
    for (int i = 0; i < [sfsListOfUsers size]; i++) {
        [listOfUsers addObject:[sfsListOfUsers getUtfString:i]];
    }
    
    // Post notification to SearchFriendsViewController toupdate his TableView with listOfUsers
    [[NSNotificationCenter defaultCenter] postNotificationName:UPDATE_LIST_OF_USERS object:self userInfo:@{ @"listOfUsers" : listOfUsers }];
    
}


// Sent in response of my CMD_GET_RANKING_LISTS request
- (void)handleRankingListResponse:(SFSObject*)params
{
    
    SFSArray *sfsWorldRankingList = [params getSFSArray:WORLD_RANKING_LIST];
    SFSArray *sfsFriendsRankingList = [params getSFSArray:FRIENDS_RANKING_LIST];
    
    NSArray *worldRankingList = [self getRankingListFromSFSRankingList:sfsWorldRankingList];
    NSArray *friendsRankingList = [self getRankingListFromSFSRankingList:sfsFriendsRankingList];
    
//    NSLog(@"worldRankingList: %@",worldRankingList);
//    NSLog(@"friendsRankingList: %@",friendsRankingList);
    
    // Post notification to SearchFriendsViewController to update his TableView with RankingList
    [[NSNotificationCenter defaultCenter] postNotificationName:UPDATE_RANKING_LISTS object:self
                                                      userInfo:@{ WORLD_RANKING_LIST : worldRankingList,
                                                                  FRIENDS_RANKING_LIST : friendsRankingList,                                                                           }];
    
}


//Send when one of the players skipped turn
- (void)handleChangeCurrentPlayer:(SFSObject*)params
{
    
    NSInteger currentPlayerID = [params getInt:ID_OF_CURRENT_PLAYER];
    
    [[GameInfo sharedInfo] setIsMyTurn:currentPlayerID == _smartFoxClient.mySelf.playerId];
    
    [self.communicationDelegate resetTimerAndShouldShowHint:[[GameInfo sharedInfo] isMyTurn] additionalDelay:0];
    
}


- (void)handleForcedGameOver:(SFSObject *)params
{
    
    [_levelAdapter handleForcedGameOverResponse:params];
    
}


- (void)handleGetAmountOfMoney:(SFSObject *)params
{
    
    NSNumber *amountOfMoney = [params getLong:AMOUNT_OF_MONEY];
    
    // Post notification to MainMenuViewController to update Money label
    [[NSNotificationCenter defaultCenter] postNotificationName:CMD_GET_AMOUNT_OF_MONEY object:self
                                                      userInfo:@{ AMOUNT_OF_MONEY : amountOfMoney }];
    
}


- (NSArray *)getRankingListFromSFSRankingList:(SFSArray *)sfsRankingList
{
    
    NSMutableArray *sfsRankingInfoList = [NSMutableArray new];
    
    // put all SFSObjects which contains userInfo in Array
    for (int i = 0; i < [sfsRankingList size]; i++) {
        [sfsRankingInfoList addObject:[sfsRankingList getSFSObject:i]];
    }
    
    NSMutableArray *userInfoList = [NSMutableArray new];
    
    // put each userInfo from SFSObject in Array
    for (int i = 0; i < [sfsRankingInfoList count]; i++) {
        
        SFSObject *sfsUserInfo = sfsRankingInfoList[i];
        
        NSString *userName = [sfsUserInfo getUtfString:NAME];
        NSString *userRank = [sfsUserInfo getUtfString:RANK];
        NSString *userWinPercentage = [sfsUserInfo getUtfString:WIN_PERCENTAGE];
        NSString *userPlayedGames = [sfsUserInfo getUtfString:PLAYED_GAMES];
        
        NSDictionary *userInfo = @{ NAME : userName,
                                    RANK : userRank,
                                    WIN_PERCENTAGE : userWinPercentage,
                                    PLAYED_GAMES : userPlayedGames };
        
        [userInfoList addObject:userInfo];
        
    }
    
    return [NSArray arrayWithArray:userInfoList];
    
}


- (void)sendSwapSFSObjectToServer:(SFSObject *)swapSFSObject
{
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_SEND_SWAP params:swapSFSObject room:_gameRoom]];
}


- (void)sendRematchGameRequest
{
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_REMATCH_GAME params:[SFSObject new] room:_gameRoom]];
}


-(void)retrieveUsersVariables
{
    
    NSArray *userlist = [_gameRoom userList];
    [GameInfo sharedInfo].isPlayingWithBot = userlist.count == 1;
    //If playing with bot populate player object from room variables
    if ( [GameInfo sharedInfo].isPlayingWithBot ) {
        [[GameInfo sharedInfo] setVariablesForBot:[self getBotInfo]];
    }
    
    for (int i = 0; i < [userlist count]; i++) {
        
        SFSUser *user = userlist[i];
        NSArray *sfsUserVariables = [user getVariables];
        
        [[GameInfo sharedInfo] setUserVariables:sfsUserVariables forUser:user.playerId];
        
    }
    
}

- (NSDictionary*)getBotInfo
{
    
    NSString* botName = [[_gameRoom getVariable:BOT_NAME] getStringValue];
    NSInteger botWins = [[_gameRoom getVariable:BOT_WINS] getIntValue];
    NSInteger botLosses = [[_gameRoom getVariable:BOT_LOSSES] getIntValue];
    NSInteger botRank = [[_gameRoom getVariable:BOT_RANK] getIntValue];
    NSInteger botHeroType = [[_gameRoom getVariable:BOT_HERO_TYPE] getIntValue];
    NSInteger botHeroProduces = [[_gameRoom getVariable:BOT_HERO_PRODUCES] getIntValue];
    NSInteger botHeroAttack = [[_gameRoom getVariable:BOT_HERO_ATTACK] getIntValue];
    
    return @{ BOT_NAME : botName,
              BOT_WINS : @(botWins),
              BOT_LOSSES : @(botLosses),
              BOT_RANK : @(botRank),
              BOT_HERO_TYPE : @(botHeroType),
              BOT_HERO_PRODUCES : @(botHeroProduces),
              BOT_HERO_ATTACK : @(botHeroAttack)};
    
}

- (NSString *)getMyUsername
{
    return [_smartFoxClient.mySelf name];
}


- (void)getRankingLists
{
    
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_GET_RANKING_LISTS params:[SFSObject new] room:nil]];
    
}

- (void)updateChosenHeroInfo
{
    
    HeroInfo *chosenHeroInfo = [HeroInfo getChosenHeroInfo];
    
    // type 2 == Int
    SFSUserVariable *heroTypeUserVariable = [SFSUserVariable variableWithName:CHOSEN_HERO_TYPE value:@(chosenHeroInfo.type) type:2];
    SFSUserVariable *heroProducesUserVariable = [SFSUserVariable variableWithName:CHOSEN_HERO_PRODUCES value:@(chosenHeroInfo.produces) type:2];
    SFSUserVariable *heroAttackUserVariable = [SFSUserVariable variableWithName:CHOSEN_HERO_ATTACK value:@(chosenHeroInfo.attack) type:2];
    
    NSArray *userVariables = [NSArray arrayWithObjects:heroTypeUserVariable, heroProducesUserVariable, heroAttackUserVariable, nil];
    
    [_smartFoxClient send:[SetUserVariablesRequest requestWithUserVariables:userVariables]];
    
}


- (void)updateMyselfMoney:(NSInteger)moneyToUpdate
{
    
    SFSObject *params = [SFSObject new];
    [params putInt:MONEY_TO_UPDATE value:moneyToUpdate];
    
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_UPDATE_MONEY_FOR_USER params:params room:nil]];
    
}


- (void)sendReturnToLobbyRequest
{
    
    SFSObject *params = [SFSObject new];
    
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_RETURN_TO_LOBBY params:params room:nil]];
    
}


- (void)getAmountOfMoneyFromServer
{
    
    SFSObject *params = [SFSObject new];
    
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_GET_AMOUNT_OF_MONEY params:params room:nil]];
    
}


- (void)getStoreInfoFromServer
{
    
    SFSObject *params = [SFSObject new];
    
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_GET_STORE_INFO params:params room:nil]];
    
}


- (void)sendUpgradeRequestForHero:(NSInteger)heroType andUpgrade:(NSInteger)upgradeType
{
    
    SFSObject *params = [SFSObject new];
    [params putInt:HERO_TYPE value:heroType];
    [params putInt:UPGRADE_TYPE value:upgradeType];
    
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_UPGRADE_HERO params:params room:nil]];
    
}


#pragma mark - Ping Timer

- (void)startPingTimer
{
    
    _pingTimer = [NSTimer scheduledTimerWithTimeInterval: 5.0 target: self
                                                      selector: @selector(sendPingRequest) userInfo: nil repeats: YES];
    
}

- (void)stopPingTimer
{
    
    // BEFORE DOING SO CHECK THAT TIMER MUST NOT BE ALREADY INVALIDATED
    // Always nil your timer after invalidating so that
    // it does not cause crash due to duplicate invalidate
    if ( _pingTimer ) {
        
        [_pingTimer invalidate];
        _pingTimer = nil;
        
    }
    
}


- (void)sendPingRequest
{
        
    SFSObject *emptyObj = [SFSObject new];
    
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_PING_REQUEST params:emptyObj room:nil]];
    
}


#pragma mark - Invitation Events
-(void)onInvitation:(SFSEvent *)evt
{
    [_invitationManager onInvitation:evt];
}


-(void)onInvitationReply:(SFSEvent *)evt
{
    [_invitationManager onInvitationReply:evt];
}


-(void)onInvitationReplyError:(SFSEvent *)evt
{
    // Show the Error on screen
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Invitation Error" message:[NSString stringWithFormat:@"onInvitationReplyError: %@",[evt.params objectForKey:@"errorMessage"]] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
    [alert show];
}


- (void)inviteBuddyToPlayGame:(NSString *)buddyname
{
    [_invitationManager inviteBuddyToPlayGame:buddyname];
}


#pragma mark - Buddies Events
// This event is fired in response to a InitBuddyListRequest.
-(void)onBuddyListInit:(SFSBuddyEvent *)evt
{
    
    NSArray *buddies = [NSArray arrayWithArray:[[_smartFoxClient buddyManager] buddyList]];
    NSLog(@"BuddyList: %@",buddies);
    
}


// Send Buddy Invitation to User
- (void)inviteUserToBuddylist:(NSString *)username
{
    [_invitationManager inviteUserToBuddyList:username];
}


// Send RemoveBuddyRequest to remove particular user from my Buddylist
- (void)removeUserFromBuddylist:(NSString *)username
{
    [_buddyManager removeUserFromBuddyList:username]; // Stefan , Petar
}


-(void)onBuddyAdd:(SFSBuddyEvent *)evt
{
    [_buddyManager onBuddyAdd:evt];
}


-(void)onBuddyError:(SFSBuddyEvent *)evt
{
    // Show the Error on screen
    NSString *errorMessage = [NSString stringWithFormat:@"%@",[evt.params objectForKey:@"errorMessage"]];
    
    NSString *message = [NSString stringWithFormat:@"onBuddyError: %@",errorMessage];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Invitation" message:message delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
    [alert show];
    
}


-(void)onBuddyVariablesUpdate:(SFSBuddyEvent *)evt
{
    NSLog(@"onBuddyVariablesUpdate:");
}


// Shows Message passed between Budies
-(void)onBuddyMessage:(SFSBuddyEvent *)evt
{
    [_buddyManager onBuddyMessage:evt];
}


- (NSArray *)getBuddyList
{
    NSArray *buddies = [[_smartFoxClient buddyManager] buddyList];
    return buddies;
}


// Send Extension Request to server to get NSArray with usernames
- (void)getListOfUsersForName:(NSString *)username
{
    
    // set Username as parameter
    SFSObject *sfsUsername = [SFSObject new];
    [sfsUsername putUtfString:USERNAME value:username];
    
    [_smartFoxClient send:[ExtensionRequest requestWithExtCmd:CMD_GET_LIST_OF_USERS_FOR_NAME params:sfsUsername room:nil]];
    
}


#pragma mark - Admin Messages
-(void)onAdminMessage:(SFSEvent *)evt
{
    
    NSString *message = [NSString stringWithFormat:@"%@",[evt.params objectForKey:@"message"]];
    
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Admin message" message:message delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
    [alert show];
    
}


#pragma mark - Helper methods

- (void)decreaseEnergy
{
    
    NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
    
    NSInteger currentEnergy = [settings integerForKey:CURRENT_ENERGY_KEY];
    BOOL isPurchasedUnlimitedEnergy = [settings boolForKey:IS_PURCHASED_UNLIMITED_ENERGY_KEY];
    
    if ( isPurchasedUnlimitedEnergy == NO ) {
        
        [settings setInteger:currentEnergy - 1 forKey:CURRENT_ENERGY_KEY];
        [settings synchronize];
        
    }
    
}

@end





